//
// WPhotoShowView.m
// PhotosBrowser
//
// Created by winter on 2016/10/24.
// Copyright © 2016年 JHJR. All rights reserved.
//

#import "WPhotoShowView.h"
#import "WPhotoBrowserConst.h"
#import "UIImageView+WebCache.h"

// cell的宽
#define WPhotoCellW (_photoCell.width > 0 ? _photoCell.width : WScreenW)
// cell的高
#define WPhotoCellH (_photoCell.height > 0 ? _photoCell.height : WScreenH)

// 旋转角为PI的整数倍
#define WHorizontal (ABS(_rotation) < 0.01 || ABS(_rotation - M_PI) < 0.01 || ABS(_rotation - M_PI * 2) < 0.01)

// 旋转角为90°或者270°
#define WVertical (ABS(_rotation - M_PI_2) < 0.01 || ABS(_rotation - M_PI_2 * 3) < 0.01)

// 预览图片时，图片最大放大倍数
#define WPreviewPhotoMaxScale 2

@interface WPhotoShowView ()<UIActionSheetDelegate, UIGestureRecognizerDelegate>
/** 单击手势 */
@property (nonatomic, weak) UIGestureRecognizer *singleTap;

/** contentScrollView的模拟锚点 */
@property (nonatomic, assign) CGPoint scrollViewAnchorPoint;
/** PhotoView的模拟锚点 */
@property (nonatomic, assign) CGPoint photoViewAnchorPoint;

/** 记录加载链接 */
@property (nonatomic, strong) NSURL *lastUrl;
/** 旋转的角度 */
@property (nonatomic, assign) CGFloat rotation;

@property (nonatomic, strong) UIButton *deleteButton;
@end

@implementation WPhotoShowView

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initialization];
    }
    return self;
}

- (void)initialization
{
    self.userInteractionEnabled = YES;
    
    WProgressView *progressView = [[WProgressView alloc] init];
    progressView.frame = CGRectMake(0, 0, 100, 100);
    progressView.hidden = YES;
    [self addSubview:progressView];
    self.progressView = progressView;
    
    // 添加加载失败
    UIImageView *loadFailureView = [[UIImageView alloc] initWithFrame:progressView.frame];
    loadFailureView.image = WLoadFailureImage;
    loadFailureView.hidden = YES;
    [self addSubview:loadFailureView];
    self.loadFailureView = loadFailureView;
    
    // 删除图片
    UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [deleteButton setTitle:@"删除" forState:UIControlStateNormal];
    [deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [deleteButton setTitleColor:[UIColor colorWithWhite:1 alpha:0.7] forState:UIControlStateHighlighted];
    deleteButton.frame = CGRectMake(0, 0, 50, 30);
    [deleteButton addTarget:self action:@selector(deleteImage) forControlEvents:UIControlEventTouchUpInside];
    // 默认隐藏
    deleteButton.hidden = YES;
    [self addSubview:deleteButton];
    self.deleteButton = deleteButton;
    
    // 设置原始锚点
    self.scrollViewAnchorPoint = self.layer.anchorPoint;
    
    // 默认放大倍数和旋转角度
    self.scale = 1.0;
    self.rotation = 0.0;
    // 取消自动布局
    self.autoresizingMask = UIViewAutoresizingNone;
    // 设置图片为默认图片
    self.image = WPlaceholderImage;
}

- (void)setPhotoCell:(WPhotoShowCell *)photoCell
{
    _photoCell = photoCell;
    [self addGestureRecognizers];
}

// 添加指定的手势
- (void)addGestureRecognizers
{
    // 添加单击手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageTapAction:)];
    [self.photoCell addGestureRecognizer:tap];
    self.singleTap = tap;
    
    // 添加双击手势
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageDidDoubleClicked:)];
    [doubleTap setNumberOfTapsRequired:2];
    [self.photoCell addGestureRecognizer:doubleTap];
    
    // 单击双击共存时，单击失效
    [self.singleTap requireGestureRecognizerToFail:doubleTap];
    
    // 添加长按手势
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(imageDidLongPress:)];
    [self.photoCell addGestureRecognizer:longPress];
    
    // 添加捏合手势
    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(imageDidPinch:)];
    [self.photoCell addGestureRecognizer:pinch];
    // 添加旋转手势
    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(photoDidRotation:)];
    [self.photoCell addGestureRecognizer:rotation];
    
    if (self.isBig) { // 预览状态，支持双击手势，支持加载进度指示器
        // 添加双击手势
        UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageDidDoubleClicked:)];
        [doubleTap setNumberOfTapsRequired:2];
        [self.photoCell addGestureRecognizer:doubleTap];
        // 单击双击共存时，避免双击失效
        [self.singleTap requireGestureRecognizerToFail:doubleTap];
    }
}

// 移除指定的手势
- (void)removeGestureRecognizers
{
    // 删除photoCell的除单击以外的手势
    for (UIGestureRecognizer *gr in self.photoCell.gestureRecognizers) {
        if (!([gr isKindOfClass:[UITapGestureRecognizer class]] && ((UITapGestureRecognizer *)gr).numberOfTapsRequired == 1)) { // 只要不是单击手势，都移除
            [self.photoCell removeGestureRecognizer:gr];
        }
    }
}

#pragma mark - action 

- (void)imageTapAction:(UITapGestureRecognizer *)tap
{
    if (self.actionBlock) {
        self.actionBlock(PhotoViewActionType_singleTap);
    }
}

- (void)imageDidLongPress:(UILongPressGestureRecognizer *)longPress
{
    if (UIGestureRecognizerStateBegan == longPress.state) {
        if (self.actionBlock) {
            self.actionBlock(PhotoViewActionType_longPress);
        }
    }
}

- (void)imageDidDoubleClicked:(UITapGestureRecognizer *)doubleTap
{
    // 设置锚点
    self.scrollViewAnchorPoint = [self setAnchorPointBaseOnGestureRecognizer:doubleTap];
    // 放大倍数（默认为放大）
    CGFloat scale = WPreviewPhotoMaxScale;
    
    CGFloat width = CGRectGetWidth(self.frame);
    if ((width - self.photoModel.verticalWidth) > 0.01) {
        scale = self.photoModel.verticalWidth / width;
    }
    
    [UIView animateWithDuration:0.25  delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        self.transform = CGAffineTransformScale(self.transform, scale, scale);
    } completion:^(BOOL finished) {
        // 记录放大倍数
        self.scale = width / self.photoModel.verticalWidth;
    }];
}

- (void)imageDidPinch:(UIPinchGestureRecognizer *)pinch
{
    if (pinch.numberOfTouches < 2) { // 只有一只手指，取消手势
        [pinch setCancelsTouchesInView:YES];
        [pinch setValue:@(UIGestureRecognizerStateEnded) forKeyPath:@"state"];
    }
    
    if (pinch.state == UIGestureRecognizerStateChanged) {
        // 获取锚点
        self.scrollViewAnchorPoint = [self setAnchorPointBaseOnGestureRecognizer:pinch];
        // 当对图片放大到最大最次放大时，缩放因子就会变小
        CGFloat scaleFactor = 1.0;
        if (self.width > WPhotoCellW * WPreviewPhotoMaxScale && pinch.scale > 1.0) {
            scaleFactor =  (1 + 0.01 * pinch.scale) /  pinch.scale;
        }
        // 记录手势
        self.rotationGesture = NO;
        self.transform = CGAffineTransformScale(self.transform, pinch.scale * scaleFactor, pinch.scale * scaleFactor);
        // 复位
        pinch.scale = 1;
    }
    
    if (pinch.state == UIGestureRecognizerStateEnded
        || pinch.state == UIGestureRecognizerStateFailed
        || pinch.state == UIGestureRecognizerStateCancelled) { // 手势结束\取消\失败
        // 判断是否缩小
        CGFloat scale = 1;
        if (WHorizontal) { // 旋转角为PI的整数倍 并且竖屏
            if (self.width <= self.photoModel.verticalWidth) { // 缩小了(旋转0°、180°、360°)
                // 放大
                scale = self.photoModel.verticalWidth / self.width;
            } else if (self.width > self.photoModel.verticalWidth * WPreviewPhotoMaxScale) { // 最大放大3倍
                scale = self.photoModel.verticalWidth * WPreviewPhotoMaxScale / self.width;
            }
        } else if (WVertical) { // 旋转角为90°或者270°
            if (originalSize.width > originalSize.height * 2) { // image高和屏幕高一样
                if (self.height < WPhotoCellH) { // 比原来小了
                    scale = WPhotoCellH / self.height;
                } else if (self.height > WPhotoCellH * WPreviewPhotoMaxScale) { // 超过了最大倍数
                    scale = WPhotoCellH * WPreviewPhotoMaxScale / self.height;
                }
            } else { // image宽和屏幕一样
                if (self.width < self.photoModel.verticalWidth) { // 比原来小了
                    scale = self.photoModel.verticalWidth / self.width;
                } else if (self.width > self.photoModel.verticalWidth * WPreviewPhotoMaxScale) { // 超过了最大倍数
                    scale = self.photoModel.verticalWidth * WPreviewPhotoMaxScale / self.width;
                }
            }
        }
        
        // 复位
        [UIView animateWithDuration:0.25  delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            self.transform = CGAffineTransformScale(self.transform, scale, scale);
        } completion:^(BOOL finished) {
            // 记录放大的倍数
            self.scale = self.width / self.photoModel.verticalWidth;
        }];
    }
}

// 记录预览时的最原始大小（未伸缩\旋转）
static CGSize originalSize;
- (void)photoDidRotation:(UIRotationGestureRecognizer *)rotation
{
    // 记录当前手势
    self.rotationGesture = YES;
    
    // 设置contentScrollView
    UIScrollView *contentScrollView = self.photoCell.contentScrollView;
    contentScrollView.contentOffset = CGPointZero;
    contentScrollView.contentInset = UIEdgeInsetsZero;
    contentScrollView.frame = CGRectMake(0, 0, WPhotoCellW, WPhotoCellH);
    self.center = CGPointMake(WPhotoCellW * 0.5, WPhotoCellH * 0.5);
    
    // 计算旋转角度
    self.transform = CGAffineTransformRotate(self.transform, rotation.rotation);
    
    if (rotation.state == UIGestureRecognizerStateEnded
        || rotation.state == UIGestureRecognizerStateFailed
        || rotation.state == UIGestureRecognizerStateCancelled) { // 手势结束\失败\取消
        
        CGAffineTransform temp = CGAffineTransformScale(self.transform, 1 / self.scale, 1 / self.scale);
        
        originalSize = self.photoModel.originalSize;
        // 获取角度
        CGFloat angle = acosf(temp.a);
        if (ABS(asinf(self.transform.b) + M_PI_2) < 0.01) { // 旋转270°
            angle += M_PI;
        }
        // 获取旋转因子
        CGFloat factor = ((int)(temp.b + 0.5)) == 1 ? 1 : -1;
        // 旋转后的宽高
        __block CGFloat width = 0;
        __block CGFloat height = 0;
        if (originalSize.width > originalSize.height * 2 || WPhotoCellW > WPhotoCellH) { // （原始图片）宽大于高的两倍(竖屏) 或者横屏
            height = WPhotoCellH;
            width = height * originalSize.height / originalSize.width;
        } else { // （原始图片）高大于宽
            height = WPhotoCellW * originalSize.width / originalSize.height;
            width = WPhotoCellW;
        }
        
        // 判断旋转角度
        if (angle < M_PI_4 || angle > M_PI * 7 / 4) { // 旋转角度在0°~45°/315°~360°之间
            angle = 0;
        } else if (angle < M_PI * 3 / 4) { // 旋转角度在45°~135°之间
            angle = M_PI_2;
        } else if (angle < M_PI * 5 / 4) { // 旋转角度在135°~225°之间
            angle = M_PI;
        } else if (angle < M_PI * 7 / 4) { // 旋转角度在225°~315°之间
            angle = M_PI_2 * 3 ;
        }
        
        // 默认为0.25秒
        [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            self.transform = CGAffineTransformMakeRotation(angle * factor);
            self.rotation = acosf(self.transform.a);
            if (ABS(asinf(self.transform.b) + M_PI_2) < 0.01) { // 旋转270°
                self.rotation += M_PI;
            }
            // 判断最终旋转角度
            if (WHorizontal) { // 旋转角为PI的倍数
                height = originalSize.height;
                width = originalSize.width;
            }
            
            self.photoModel.verticalWidth = width > WPhotoCellW ? WPhotoCellW : width;
            self.origin = CGPointZero;
            self.size = CGSizeMake(width, height);
            contentScrollView.size = CGSizeMake(self.width > WPhotoCellW ? WPhotoCellW : self.width, self.height > WPhotoCellH ? WPhotoCellH : self.height);
            contentScrollView.contentSize = self.size;
            contentScrollView.center = CGPointMake(WPhotoCellW * 0.5, WPhotoCellH * 0.5);
            contentScrollView.contentOffset = CGPointZero;
        } completion:^(BOOL finished) {
            self.rotationGesture = NO;
        }];
    }
    // 复位（如果不复位，会导致乱转）
    rotation.rotation = 0;
}

#pragma mark - private method

- (void)animateWithFromFrame:(CGRect)fromFrame animations:(void (^)(void))animations
{
    CGRect objFrame = self.frame;
    self.frame = fromFrame;
    [UIView animateWithDuration:0.5 animations:^{
        self.frame = objFrame;
        if (animations) {
            animations();
        }
    }];
}

// 监听transform
- (void)setTransform:(CGAffineTransform)transform
{
    [super setTransform:transform];
    
    // 如果手势没结束、没有放大、旋转手势，返回
    if (self.isRotationGesture) return;
    
    // 调整scrollView
    // 恢复photoView的x/y位置
    self.origin = CGPointZero;
    // 修改contentScrollView的属性
    UIScrollView *contentScrollView = self.photoCell.contentScrollView;
    contentScrollView.height = self.height < WPhotoCellH ? self.height : WPhotoCellH;
    contentScrollView.width = self.width < WPhotoCellW ? self.width : WPhotoCellW;
    contentScrollView.contentSize = self.size;
    // 根基模拟锚点调整偏移量
    CGFloat offsetX = contentScrollView.contentSize.width * self.scrollViewAnchorPoint.x - contentScrollView.width * self.photoViewAnchorPoint.x;
    CGFloat offsetY = contentScrollView.contentSize.height * self.scrollViewAnchorPoint.y - contentScrollView.height * self.photoViewAnchorPoint.y;
    
    if (ABS(offsetX) + contentScrollView.width > contentScrollView.contentSize.width) { // 偏移量超出范围
        offsetX = offsetX > 0 ? contentScrollView.contentSize.width - contentScrollView.width : contentScrollView.width - contentScrollView.contentSize.width;
    }
    if (ABS(offsetY) + contentScrollView.height > contentScrollView.contentSize.height) {  // 偏移量超出范围
        offsetY = offsetY > 0 ? contentScrollView.contentSize.height - contentScrollView.height :
        contentScrollView.height - contentScrollView.contentSize.height;
    }
    // 最后调整
    offsetX = offsetX < 0 ? 0 : offsetX;
    offsetY = offsetY < 0 ? 0 : offsetY;
    contentScrollView.contentOffset = CGPointMake(offsetX, offsetY);
    contentScrollView.center = CGPointMake(WPhotoCellW * 0.5, WPhotoCellH * 0.5);
}

/** 根据手势触摸点修改相应的锚点，就是沿着触摸点做相应的手势操作 */
- (CGPoint)setAnchorPointBaseOnGestureRecognizer:(UIGestureRecognizer *)gr
{
    // 手势为空 直接返回
    if (!gr) return CGPointMake(0.5, 0.5);
    
    // 创建锚点
    CGPoint anchorPoint; // scrollView的虚拟锚点
    CGPoint viewAnchorPoint; // photoCell的虚拟锚点
    UIScrollView *scrollView = (UIScrollView *)[self superview];
    if ([gr isKindOfClass:[UIPinchGestureRecognizer class]]) { // 捏合手势
        if (gr.numberOfTouches == 2) {
            // 当触摸开始时，获取两个触摸点
            // 获取滚动视图上的触摸点
            CGPoint point1 = [gr locationOfTouch:0 inView:scrollView];
            CGPoint point2 = [gr locationOfTouch:1 inView:scrollView];
            anchorPoint.x = (point1.x + point2.x) / 2.0 / scrollView.contentSize.width;
            anchorPoint.y = (point1.y + point2.y) / 2.0 / scrollView.contentSize.height;
            // 获取cell上的触摸点
            CGPoint screenPoint1 = [gr locationOfTouch:0 inView:gr.view];
            CGPoint screenPoint2 = [gr locationOfTouch:1 inView:gr.view];
            viewAnchorPoint.x = (screenPoint1.x + screenPoint2.x) / 2.0 / gr.view.width;
            viewAnchorPoint.y = (screenPoint1.y + screenPoint2.y) / 2.0 / gr.view.height;
        }
    } else if ([gr isKindOfClass:[UITapGestureRecognizer class]]) { // 点击手势
        // 获取scrollView触摸点
        CGPoint scrollViewPoint = [gr locationOfTouch:0 inView:scrollView];
        anchorPoint.x = scrollViewPoint.x / scrollView.contentSize.width;
        anchorPoint.y = scrollViewPoint.y / scrollView.contentSize.height;
        // 获取cell上的触摸点
        CGPoint photoCellPoint = [gr locationOfTouch:0 inView:gr.view];
        viewAnchorPoint.x = photoCellPoint.x / gr.view.width;
        viewAnchorPoint.y = photoCellPoint.y / gr.view.height;
    };
    self.photoViewAnchorPoint = viewAnchorPoint;
    return anchorPoint;
}

- (void)deleteImage
{

}

#pragma mark - lazy

- (void)setPhotoModel:(WPhotoModel *)photoModel
{
    _photoModel = photoModel;
    
    if (photoModel.thumbnailImageUrl.length > 0) {
        // 获取缩略图
        [self sd_setImageWithURL:[NSURL URLWithString:photoModel.thumbnailImageUrl]];
    }
    // 缩略图
    UIImage *tempImage = self.image;
    if (tempImage) {
        self.photoModel.originalSize = CGSizeMake(self.width, self.width * tempImage.size.height / tempImage.size.width);
    }
    // 大图
    [self sd_setImageWithURL:[NSURL URLWithString:photoModel.originalImageUrl]];
}

@end
